//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<varying_data.h>
///	@path	~/src/object/
///	@date	2007/12/03
///	@desc	Varying data, object type is not consist.

#pragma once

#include "xeres.h"

// math
#include "lib/math/pair.h"
#include "lib/math/vector.h"
#include "lib/math/quat.h"
#include "lib/math/matrix.h"
#include "lib/math/color.h"

#include "object/IObject.h"

namespace xeres {

	enum VaryingDataType{
		VAR_VOID = 0 ,
		VAR_BOOL ,
		VAR_INT ,
		VAR_FLOAT ,
		VAR_PAIR ,
		VAR_VECTOR ,
		VAR_QUAT ,
		VAR_COLOR ,
		VAR_MATRIX ,
		VAR_STRING ,
		VAR_IOBJECT ,
		VAR_last
	};

	/*!
		\class	VaryingData
		\brief	A common value representation class.
		\details
			Some classes uses varying data, such as CVar or CValueEntry.<BR>
			VaryingData provide an encapsulated way to manipulate varying(or typeless) data.
	*/
	class VaryingData
	{
	public:

		/// \name Constructor & Destructor
		//@{

		/// @ctor
		VaryingData( void );

		/// @dtor
		~VaryingData( void );

		//@}

		/// \name RTTI Functions
		//@{

		/// Get internal data type name.
		/// \sa IVar::GetVarTypeName
		const WString& GetVarTypeName( void ) const;

		/// Get internal data type ID.
		/// \sa IVar::GetVarTypeID
		const ClassID GetVarTypeID( void ) const;
		//@}

		/// Provide a duplicate operation.
		/// \sa IVar::DuplicateFrom
		bool DuplicateFrom( const VaryingData& val );

		// Set accessors.
		bool SetBool( bool val );
		bool SetInt( int val );
		bool SetFloat( float val );
		bool SetPair( const Pair<float>& val );
		bool SetVector( const Vector<float>& val );
		bool SetQuat( const Quat<float>& val );
		bool SetColor( const Color4& val );
		bool SetMatrix( const Matrix<float>& val );
		bool SetString( const WString& val );

		bool SetObject( RefWeak<IObject> val );

		// Get accessors.
		bool GetBool( bool& val ) const;
		bool GetInt( int& val ) const;
		bool GetFloat( float& val ) const;
		bool GetPair( Pair<float>& val ) const;
		bool GetVector( Vector<float>& val ) const;
		bool GetQuat( Quat<float>& val ) const;
		bool GetColor( Color4& val ) const;
		bool GetMatrix( Matrix<float>& val ) const;
		bool GetString( WString& val ) const;

		bool GetObject( Ref<IObject>& val ) const;

		/// Get data type.
		/// \return Internal data type proxy.
		VaryingDataType GetVaryingDataType( void ) const { return m_type; }

		/// Set data type( or change data type ).
		/// \param[in]	type		Type to set internal data.
		/// \param[in]	invariant	Indicates if internal data type is invariant, cannot be changed any more.
		void SetType( VaryingDataType type , bool invariant );

	private:

		// Internal change type.
		inline bool ChangeType( VaryingDataType newType );

		// Internal delete variable data.
		inline void DeleteData( void );

		// data

		VaryingDataType		m_type : 16;
		bool				m_invariant;
		bool				m_spare;

		// internal data representation
		union
		{
			bool			u_asBool;
			int				u_asInt;
			float			u_asFloat;
			Pair<float> *	u_asPair;
			Vector<float> *	u_asVector;
			Quat<float> *	u_asQuat;
			Color4 *		u_asColor;
			Matrix<float> *	u_asMatrix;
			WString *		u_asString;
			IObject *		u_asObject;

			void *			u_asPtr;
		} m_data;
	};

} // namespace xeres
